package com.hns.can.master.service;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import au.com.bytecode.opencsv.CSVReader;

import com.hns.can.common.entity.BaseEntity;
import com.hns.can.master.common.AbstractImportByFile;
import com.hns.can.master.common.IFileDataProcessor;
import com.hns.can.master.common.ImportDataFactory;
import com.hns.frame.dao.CommonEntityDao;
import com.hns.tool.pub.UtilString;


/**
 * 项目名称：can
 * 类名称：ImportRSVFileService
 * 类描述：导入CSV文件的组件
 * 创建人：yecb
 * 创建时间：2014年9月18日 下午1:53:32
 * 修改人：yecb
 * 修改时间：2014年9月18日 下午1:53:32
 * 修改备注：
 * 
 * @version 1.0
 */
@Service
public class ImportCSVFileService extends AbstractImportByFile {
    
    @Autowired
    public CommonEntityDao commonEntityDao;
    
    private static final Logger logger = LoggerFactory.getLogger(ImportCSVFileService.class);
    
    private HashMap<String, Map<Integer, String>> templeCache = new HashMap<String, Map<Integer, String>>();
    
    private static String workdir = Thread.currentThread().getContextClassLoader().getResource("") + "\\ImportTemple.xml";
    
    private String xmlTableName;// 配置文件的对应表格
                                                                                                                                                       
    private String can_type;// 类型，对应导入数据属于哪张表
                                                                                                                                                       
    public void setXmlTableName(String xmlTableName) {
        this.xmlTableName = xmlTableName;
    }
    
    public void setCan_type(String can_type) {
        this.can_type = can_type;
    }
    
    /**
     * doImportRSVFile(导入对应的文件)
     */
    @SuppressWarnings("rawtypes")
    @Transactional(rollbackFor = Exception.class)
    public List<? extends BaseEntity> doImportCSVFile(Class object, String file, String xmlTableName, String can_type) throws Exception {
        this.xmlTableName = xmlTableName;
        this.can_type = can_type;
        
        Long beginTime = System.currentTimeMillis();
        List<? extends BaseEntity> baseEntityList = importFromFile(object, file);
        for (int i = 0; i < baseEntityList.size(); i++) {
            try {
                commonEntityDao.save(baseEntityList.get(i));
            } catch (Exception e) {
                throw new Exception("导入数据有误，保存不成功！");
            }
            if (i % 1000 == 0) {
                commonEntityDao.flush();
            }
        }
        Long endTime = System.currentTimeMillis();
        
        logger.info("文件导入数据库的处理时间:" + (endTime - beginTime));//文件从解析到存入数据所花时间
        return baseEntityList;
    }
    
    @Override
    protected String getFileType() {
        return ".csv";
    }
    
    @Override
    protected void dealProcessor(List<BaseEntity> baseEntitys) throws Exception {
        IFileDataProcessor dataProcessor;
        try {
            dataProcessor = (IFileDataProcessor) Class.forName(ImportDataFactory.getinstance().getFileDataProcessor(can_type)).newInstance();
            dataProcessor.processData(baseEntitys);
        } catch (Exception e) {
            throw new Exception("文件处理类实例化处理异常:" + e.getMessage());
        }
    }
    
    @SuppressWarnings({"unchecked", "rawtypes" })
    private Map<Integer, String> getColumnByCSV() throws Exception {
        try {
            if (templeCache.get(xmlTableName) != null) {
                return templeCache.get(xmlTableName);
            } else {
                HashMap<Integer, String> columnMap = new HashMap<Integer, String>();//返回值
                SAXReader reader = new SAXReader();
                Document document = reader.read(workdir);
                List<Element> elements = document.selectNodes("/CONFIG/TABLE[@name='" + xmlTableName + "']");
                for (Element element : elements) {
                    for (Iterator columnIterator = element.elementIterator(); columnIterator.hasNext();) {
                        Element columnElement = (Element) columnIterator.next();
                        columnMap.put(Integer.parseInt(columnElement.attributeValue("index")), columnElement.attributeValue("columnName").toString());
                    }
                }
                templeCache.put(xmlTableName, columnMap);
                return columnMap;
            }
        } catch (DocumentException e) {
            throw new Exception("解析XML配置出现错误:" + e.getMessage(), e);
        }
    }
    
    @Override
    protected List<Map<String, Object>> getListMapByFile(String file) throws Exception {
        List<Map<String, Object>> dataMaps = new ArrayList<Map<String, Object>>();//返回值
        CSVReader csvReader = null;
        Map<Integer, String> columnMap = getColumnByCSV();//根据xmlTableName，解析ImportTemple.xml文件的内容
        try {
            csvReader = new CSVReader(new BufferedReader(new InputStreamReader(new FileInputStream(file))), ',');
            if (csvReader != null) {
                String[] csvRow = csvReader.readNext();//先读取一行，第一行为注释行，这样第一行的数据就不要了。
                while ((csvRow = csvReader.readNext()) != null) {
                    HashMap<String, Object> csvMap = new HashMap<String, Object>();
                    for (int i = 0; i < csvRow.length; i++) {
                        if (!UtilString.isEmpty(csvRow[i])) {
                            if (!UtilString.isEmpty(columnMap.get(i))) {
                                csvMap.put(columnMap.get(i)/*字段名*/, csvRow[i]/*字段值*/);
                            }
                        }
                    }
                    dataMaps.add(csvMap);
                }
            }
        } catch (Exception e) {
            throw new Exception("文件读取发生异常:" + e.getMessage(), e);
        } finally {
            if (csvReader != null) {
                csvReader.close();
            }
        }
        return dataMaps;
    }
    
}
